﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.IO;

namespace UnitTestGetFile
{
    [TestClass]
    public class UnitTestGetFile
    {
        private int statuscode = 0;
        private string statustext = "";
        private string data = "";
        [TestMethod]
        public void ExecutePlugin_WithExistingPathToFile_ShouldReturnValidFileResponse()
        {
            TcpListener server = new TcpListener(IPAddress.Any, 55123);

            ParameterizedThreadStart pts = new ParameterizedThreadStart(this.newThreadMethod);
            Thread thread = new Thread(pts);
            thread.Start(server);

            TcpClient client = new TcpClient("127.0.0.1", 55123);
            NetworkStream stream = client.GetStream();
            StreamWriter writer = new StreamWriter(stream);
            writer.WriteLine("GET /höhöö/bla.txt HTTP/1.1");
            writer.WriteLine("Host: localhost");
            writer.WriteLine("User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12");
            writer.WriteLine("Connection: close");
            writer.Flush();
            client.Close();

            thread.Join(); //warten bis Response vom anderen Thread generiert wurde

            Assert.AreEqual(200, statuscode);
            Assert.AreEqual("OK", statustext, true);
        }

        [TestMethod]
        public void ExecutePlugin_WithNonExistingPathToFile_ShouldReturn404Response()
        {
            TcpListener server = new TcpListener(IPAddress.Any, 55123);

            ParameterizedThreadStart pts = new ParameterizedThreadStart(this.newThreadMethod);
            Thread thread = new Thread(pts);
            thread.Start(server);

            TcpClient client = new TcpClient("127.0.0.1", 55123);
            NetworkStream stream = client.GetStream();
            StreamWriter writer = new StreamWriter(stream);
            writer.WriteLine("GET /existiert/nicht.jpg HTTP/1.1");
            writer.WriteLine("Host: localhost");
            writer.WriteLine("User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12");
            writer.WriteLine("Connection: close");
            writer.Flush();
            client.Close();
            
            thread.Join(); //warten bis Response vom anderen Thread generiert wurde

            Assert.AreEqual(404, statuscode);
            Assert.AreEqual("Not Found", statustext, true);
        }

        [TestMethod]
        public void ExecutePlugin_WithExistingPathToRootDirectory_ShouldReturnValidDirectoryListingResponse()
        {
            TcpListener server = new TcpListener(IPAddress.Any, 55123);

            ParameterizedThreadStart pts = new ParameterizedThreadStart(this.newThreadMethod);
            Thread thread = new Thread(pts);
            thread.Start(server);

            TcpClient client = new TcpClient("127.0.0.1", 55123);
            NetworkStream stream = client.GetStream();
            StreamWriter writer = new StreamWriter(stream);
            writer.WriteLine("GET / HTTP/1.1");
            writer.WriteLine("Host: localhost");
            writer.WriteLine("User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12");
            writer.WriteLine("Connection: close");
            writer.Flush();
            client.Close();

            thread.Join(); //warten bis Response vom anderen Thread generiert wurde

            Assert.AreEqual(200, statuscode);
            Assert.AreEqual("OK", statustext, true);
            bool b = data.Contains("Listing of Directory /");
            Assert.IsTrue(b);
        }

        [TestMethod]
        public void ExecutePlugin_WithExistingPathToNonRootDirectory_ShouldReturnValidDirectoryListingResponse()
        {
            TcpListener server = new TcpListener(IPAddress.Any, 55123);

            ParameterizedThreadStart pts = new ParameterizedThreadStart(this.newThreadMethod);
            Thread thread = new Thread(pts);
            thread.Start(server);

            TcpClient client = new TcpClient("127.0.0.1", 55123);
            NetworkStream stream = client.GetStream();
            StreamWriter writer = new StreamWriter(stream);
            writer.WriteLine("GET /Ordner%201/Bla HTTP/1.1");
            writer.WriteLine("Host: localhost");
            writer.WriteLine("User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12");
            writer.WriteLine("Connection: close");
            writer.Flush();
            client.Close();

            thread.Join(); //warten bis Response vom anderen Thread generiert wurde

            Assert.AreEqual(200, statuscode);
            Assert.AreEqual("OK", statustext, true);
            bool b = data.Contains("Listing of Directory /Ordner 1/Bla");
            Assert.IsTrue(b);
        }

        [TestMethod]
        public void ExecutePlugin_WithNonExistingPathToDirectory_ShouldReturn404Response()
        {
            TcpListener server = new TcpListener(IPAddress.Any, 55123);

            ParameterizedThreadStart pts = new ParameterizedThreadStart(this.newThreadMethod);
            Thread thread = new Thread(pts);
            thread.Start(server);

            TcpClient client = new TcpClient("127.0.0.1", 55123);
            NetworkStream stream = client.GetStream();
            StreamWriter writer = new StreamWriter(stream);
            writer.WriteLine("GET /Ordner%201/Bla/ExistiertNicht/ HTTP/1.1");
            writer.WriteLine("Host: localhost");
            writer.WriteLine("User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12");
            writer.WriteLine("Connection: close");
            writer.Flush();
            client.Close();

            thread.Join(); //warten bis Response vom anderen Thread generiert wurde

            Assert.AreEqual(404, statuscode);
            Assert.AreEqual("Not Found", statustext, true);
        }

        private void newThreadMethod(Object parameter)
        {
            TcpListener server = (TcpListener)parameter;
            server.Start();
            Socket so = server.AcceptSocket();
            IPlugin.Request req = new IPlugin.Request(so);
            req.Parse();

            Plugin.Plugin getFilePlugin = new Plugin.Plugin();
            IPlugin.Response resp = getFilePlugin.ExecutePlugin(req);
            statuscode = resp.StatusCode;
            statustext = resp.StatusText;
            data = resp.Data;

            server.Stop();
        }

    }
}
